package org.ysling.litemall.core.tasks.service;
/**
 *  Copyright (c) [ysling] [927069313@qq.com]
 *  [litemall-plus] is licensed under Mulan PSL v2.
 *  You can use this software according to the terms and conditions of the Mulan PSL v2.
 *  You may obtain a copy of Mulan PSL v2 at:
 *              http://license.coscl.org.cn/MulanPSL2
 *  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 *  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *  See the Mulan PSL v2 for more details.
 */
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.ysling.litemall.core.service.ActionLogService;

import javax.annotation.PostConstruct;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;

@Component
public class TaskService {


    @Autowired
    private ActionLogService logService;
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    /**延时队列*/
    private final DelayQueue<Task> delayQueue =  new DelayQueue<>();

    @PostConstruct
    private void init() {
        Executors.newSingleThreadExecutor().execute(() -> {
            while (true) {
                //手动开启事务
                TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
                try {
                    // 获取队列
                    Task task = delayQueue.take();
                    // 队列运行
                    task.run();
                    //手动提交事务
                    dataSourceTransactionManager.commit(transactionStatus);//提交
                } catch (Exception e) {
                    e.printStackTrace();
                    //手动回滚事务 最好是放在catch 里面,防止程序异常而事务一直卡在哪里未提交
                    dataSourceTransactionManager.rollback(transactionStatus);
                    //记录异常操作
                    logService.logOrderFail("系统处理延时任务", e.getMessage());
                }
            }
        });
    }

    public void addTask(Task task){
        if(delayQueue.contains(task)){
            return;
        }
        delayQueue.add(task);
    }

    public void removeTask(Task task){
        delayQueue.remove(task);
    }

}
